/*!
 * LLM为中心的C到Rust转换器
 * 
 * 让LLM做主要的代码转换工作，静态分析只提供上下文
 */

use anyhow::{Result, Context};
use std::collections::HashMap;

use crate::code_splitter::CodeSplitter;
use crate::llm::LlmAssistant;
use crate::file_scanner::{CFile, ScanResult, FileScanner};
use crate::project_builder::ProjectBuilder;
use crate::smart_fixer::SmartFixer;

/// 转换后的Rust模块
#[derive(Debug, Clone)]
pub struct RustModule {
    pub name: String,
    pub content: String,
    pub imports: Vec<String>,
}

/// 转换后的Rust项目
#[derive(Debug)]
pub struct RustProject {
    pub name: String,
    pub modules: Vec<RustModule>,
    pub dependencies: Vec<String>,
    pub is_binary: bool,
}

/// LLM转换器 - 核心转换逻辑
pub struct LlmConverter {
    llm: LlmAssistant,
    header_cache: HashMap<String, Option<String>>, // 缓存头文件转换结果
}

impl LlmConverter {
    pub fn new(llm: LlmAssistant) -> Self {
        Self {
            llm,
            header_cache: HashMap::new(),
        }
    }
    
    /// 转换整个C项目
    pub async fn convert_project(&mut self, scan_result: ScanResult, project_name: &str) -> Result<RustProject> {
        log::info!("开始LLM转换项目: {}", project_name);
        
        let mut rust_modules = Vec::new();
        let mut all_dependencies = std::collections::HashSet::new();
        
        // 转换源文件
        for c_file in scan_result.source_files {
            log::info!("转换源文件: {:?}", c_file.path);
            
            match self.convert_c_file(&c_file).await {
                Ok(rust_module) => {
                    // 收集依赖
                    for import in &rust_module.imports {
                        if import.starts_with("std::") || import.starts_with("libc::") {
                            if import.starts_with("libc::") {
                                all_dependencies.insert("libc".to_string());
                            }
                        }
                    }
                    rust_modules.push(rust_module);
                }
                Err(e) => {
                    log::error!("转换文件失败 {:?}: {}", c_file.path, e);
                    return Err(anyhow::anyhow!(
                        "项目转换失败，文件 {:?} 无法转换: {}\n\n提示：请检查API密钥是否正确，或稍后重试避免API限制",
                        c_file.path, e
                    ));
                }
            }
        }
        
        // 检查是否为二进制项目（有main函数）
        let is_binary = rust_modules.iter()
            .any(|module| module.content.contains("fn main(") || module.name == "main");
        
        let dependencies: Vec<String> = all_dependencies.into_iter().collect();
        
        log::info!("项目转换完成: {} 个模块, {} 个依赖", 
                  rust_modules.len(), dependencies.len());
        
        Ok(RustProject {
            name: project_name.to_string(),
            modules: rust_modules,
            dependencies,
            is_binary,
        })
    }
    
    /// 转换单个C文件
    async fn convert_c_file(&mut self, c_file: &CFile) -> Result<RustModule> {
        let module_name = FileScanner::escape_rust_keyword(
            &FileScanner::get_module_name(&c_file.path)
        );
        
        // 让LLM分析文件结构
        log::debug!("LLM分析文件结构: {:?}", c_file.path);
        let analysis = self.llm.analyze_c_file(&c_file.content).await
            .map_err(|e| anyhow::anyhow!("LLM分析文件失败 {:?}: {}", c_file.path, e))?;
        
        // 转换头文件导入
        let mut rust_imports = Vec::new();
        for include in &analysis.includes {
            match self.convert_header(include).await {
                Ok(Some(rust_import)) => {
                    // 确保不是无效的导入
                    if !rust_import.is_empty() && rust_import != "SKIP" {
                        rust_imports.push(rust_import);
                    }
                }
                Ok(None) => {
                    // 跳过这个头文件
                    log::debug!("跳过头文件: {}", include);
                }
                Err(e) => {
                    return Err(anyhow::anyhow!("转换头文件失败 {}: {}", include, e));
                }
            }
        }
        
        // 生成上下文信息
        let context = format!(
            "文件用途: {}\n函数列表: {}\n全局变量: {}\n头文件: {}",
            analysis.main_purpose,
            analysis.functions.join(", "),
            analysis.global_vars.join(", "),
            analysis.includes.join(", ")
        );
        
        // 检查文件大小，决定是否分块转换
        let code_lines = c_file.content.lines().count();
        let rust_code = if code_lines > 600 {
            log::warn!("⚠️  文件较大 ({} 行)，使用分块转换策略", code_lines);
            self.convert_large_file(&c_file.content, &context, &analysis).await
                .map_err(|e| anyhow::anyhow!("LLM分块转换失败 {:?}: {}", c_file.path, e))?
        } else {
            // 让LLM转换整个文件
            log::debug!("LLM转换代码: {:?}", c_file.path);
            self.llm.convert_function(&c_file.content, &context).await
                .map_err(|e| anyhow::anyhow!("LLM代码转换失败 {:?}: {}", c_file.path, e))?
        };
        
        // 生成完整的模块内容
        let mut module_content = String::new();
        
        // 添加文档注释
        module_content.push_str(&format!(
            "//! 模块: {}\n//!\n//! 原始文件: {:?}\n//! 用途: {}\n//!\n",
            module_name, c_file.path, analysis.main_purpose
        ));
        
        // 添加导入
        if !rust_imports.is_empty() {
            module_content.push('\n');
            for import in &rust_imports {
                module_content.push_str(&format!("use {};\n", import));
            }
            module_content.push('\n');
        }
        
        // 添加转换后的代码
        module_content.push_str(&rust_code);
        
        Ok(RustModule {
            name: module_name,
            content: module_content,
            imports: rust_imports,
        })
    }
    
    /// 分块转换大文件
    async fn convert_large_file(&mut self, c_code: &str, context: &str, analysis: &crate::llm::FileAnalysis) -> Result<String> {
        let splitter = CodeSplitter::new(200); 
        let chunks = splitter.split_large_file(c_code, &analysis.functions)?;
        
        let mut rust_chunks = Vec::new();
        
        for (idx, chunk) in chunks.iter().enumerate() {
            log::info!("正在转换片段 {}/{} (行 {}-{})", 
                      idx + 1, chunks.len(), chunk.start_line, chunk.end_line);
            
            let chunk_context = format!(
                "{}\n片段信息: 行 {}-{}, 包含函数: {}",
                context, chunk.start_line, chunk.end_line, chunk.functions.join(", ")
            );
            
            match self.llm.convert_function(&chunk.content, &chunk_context).await {
                Ok(rust_code) => {
                    rust_chunks.push(rust_code);
                    log::info!("  ✓ 片段 {} 转换成功", idx + 1);
                }
                Err(e) => {
                    log::error!("  ✗ 片段 {} 转换失败: {}", idx + 1, e);
                    return Err(anyhow::anyhow!("分块转换失败: {}", e));
                }
            }
        }
        
        // 合并所有片段
        let combined = rust_chunks.join("\n\n// ========== 下一个代码片段 ==========\n\n");
        log::info!("✓ 所有 {} 个片段已合并", chunks.len());
        
        Ok(combined)
    }
    
    /// 转换C头文件到Rust导入（带缓存）
    async fn convert_header(&mut self, header: &str) -> Result<Option<String>> {
        // 检查缓存
        if let Some(cached_result) = self.header_cache.get(header) {
            return Ok(cached_result.clone());
        }
        
        // LLM转换
        let result = self.llm.convert_header(header).await
            .map_err(|e| anyhow::anyhow!("LLM转换头文件失败 {}: {}", header, e))?;
        
        // 缓存结果
        self.header_cache.insert(header.to_string(), result.clone());
        
        Ok(result)
    }
    
    /// 自动修复编译错误的反馈循环
    pub async fn auto_fix_compile_errors(&mut self, project: &mut RustProject, project_path: &std::path::Path) -> Result<()> {
        const MAX_FIX_ITERATIONS: u32 = 3;
        
        let builder = ProjectBuilder::new();
        
        for iteration in 1..=MAX_FIX_ITERATIONS {
            log::info!("🔧 第{}轮编译检查和自动修复...", iteration);
            
            // 编译检查
            let compile_result = builder.compile_check(project_path)?;
            
            if compile_result.success {
                log::info!("🎉 编译检查通过！修复完成。");
                if !compile_result.warnings.is_empty() {
                    log::info!("⚠️  存在 {} 个警告，但编译成功", compile_result.warnings.len());
                }
                return Ok(());
            }
            
            log::warn!("发现 {} 个编译错误，尝试自动修复...", compile_result.errors.len());
            
            // 首先打印完整的编译输出用于调试
            log::error!("===== 完整编译输出 =====");
            log::error!("{}", compile_result.full_output);
            log::error!("=========================");
            
            // 按文件分组错误
            let mut errors_by_file = std::collections::HashMap::new();
            for error in compile_result.errors {
                log::debug!("解析到错误: 文件='{}', 消息='{}', 行={:?}", 
                           error.file, error.message, error.line_number);
                errors_by_file.entry(error.file.clone()).or_insert_with(Vec::new).push(error);
            }
            
            let mut fixed_any = false;
            
            // 修复每个有错误的文件
            for (file_name, file_errors) in errors_by_file {
                // 检查是否是模块文件
                if let Some(module) = project.modules.iter_mut().find(|m| {
                    let expected_file = format!("src/{}.rs", m.name);
                    expected_file == file_name || file_name.ends_with(&format!("{}.rs", m.name))
                }) {
                    log::info!("修复模块 '{}' 中的 {} 个错误", module.name, file_errors.len());
                    
                    // 检查文件大小，决定使用整体修复还是分块修复
                    let content_lines = module.content.lines().count();
                    
                    if content_lines > 500 {
                        log::warn!("⚠️  模块较大 ({} 行)，使用智能分块修复策略", content_lines);
                        
                        // 按错误位置分组（相近的错误一起修复）
                        let error_groups = SmartFixer::group_errors_by_proximity(&file_errors, 100);
                        log::info!("将 {} 个错误分为 {} 组进行修复", file_errors.len(), error_groups.len());
                        
                        let mut current_content = module.content.clone();
                        
                        for (group_idx, error_group) in error_groups.iter().enumerate() {
                            log::info!("  修复第 {}/{} 组错误 ({} 个错误)", 
                                      group_idx + 1, error_groups.len(), error_group.len());
                            
                            // 提取第一个错误周围的代码上下文
                            if let Ok((context, start_line, end_line)) = 
                                SmartFixer::extract_error_context(&current_content, &error_group[0], 50) {
                                
                                log::info!("    提取上下文: 行 {}-{} ({} 行)", 
                                          start_line, end_line, end_line - start_line + 1);
                                
                                // 让 LLM 只修复这个片段
                                let context_prompt = format!("src/{}.rs (行 {}-{})", module.name, start_line, end_line);
                                
                                match self.llm.fix_compile_errors(&context, error_group, &context_prompt).await {
                                    Ok(fixed_context) => {
                                        // 合并修复后的代码回原文件
                                        match SmartFixer::merge_fixed_context(
                                            &current_content, &fixed_context, start_line, end_line
                                        ) {
                                            Ok(merged) => {
                                                current_content = merged;
                                                log::info!("    ✓ 第 {} 组修复成功", group_idx + 1);
                                            }
                                            Err(e) => {
                                                log::error!("    ✗ 合并修复代码失败: {}", e);
                                            }
                                        }
                                    }
                                    Err(e) => {
                                        log::error!("    ✗ 第 {} 组修复失败: {}", group_idx + 1, e);
                                    }
                                }
                            }
                        }
                        
                        // 更新模块内容
                        if current_content != module.content {
                            let old_len = module.content.len();
                            module.content = current_content;
                            log::info!("模块 '{}' 智能修复完成: {} -> {} 字符", 
                                      module.name, old_len, module.content.len());
                            fixed_any = true;
                            
                            // 重新写入文件
                            let file_path = project_path.join("src").join(format!("{}.rs", module.name));
                            std::fs::write(&file_path, &module.content)
                                .with_context(|| format!("写入修复后的文件失败: {:?}", file_path))?;
                        }
                    } else {
                        // 文件不大，使用整体修复
                        log::info!("使用整体修复策略（文件较小: {} 行）", content_lines);
                        
                        log::info!("===== 修复前的代码片段 =====");
                        log::info!("{}", &module.content[..module.content.len().min(500)]);
                        log::info!("===============================");
                        
                        match self.llm.fix_compile_errors(&module.content, &file_errors, &file_name).await {
                            Ok(fixed_content) => {
                                log::info!("===== 修复后的代码片段 =====");
                                log::info!("{}", &fixed_content[..fixed_content.len().min(500)]);
                                log::info!("===============================");
                                
                                // 更新模块内容
                                let old_len = module.content.len();
                                module.content = fixed_content.clone();
                                log::info!("模块 '{}' 修复完成: {} -> {} 字符", 
                                          module.name, old_len, module.content.len());
                                fixed_any = true;
                                
                                // 重新写入文件
                                let file_path = project_path.join("src").join(format!("{}.rs", module.name));
                                std::fs::write(&file_path, &module.content)
                                    .with_context(|| format!("写入修复后的文件失败: {:?}", file_path))?;
                            }
                            Err(e) => {
                                log::error!("修复模块 '{}' 失败: {}", module.name, e);
                            }
                        }
                    }
                }
                // 检查是否是 main.rs
                else if file_name.ends_with("main.rs") {
                    log::info!("修复 main.rs 中的 {} 个错误", file_errors.len());
                    
                    let main_path = project_path.join("src").join("main.rs");
                    if let Ok(current_content) = std::fs::read_to_string(&main_path) {
                        log::info!("===== 修复前的 main.rs 代码片段 =====");
                        log::info!("{}", &current_content[..current_content.len().min(500)]);
                        log::info!("===============================");
                        
                        match self.llm.fix_compile_errors(&current_content, &file_errors, &file_name).await {
                            Ok(fixed_content) => {
                                log::info!("===== 修复后的 main.rs 代码片段 =====");
                                log::info!("{}", &fixed_content[..fixed_content.len().min(500)]);
                                log::info!("===============================");
                                
                                std::fs::write(&main_path, &fixed_content)
                                    .with_context(|| format!("写入修复后的 main.rs 失败: {:?}", main_path))?;
                                fixed_any = true;
                            }
                            Err(e) => {
                                log::error!("修复 main.rs 失败: {}", e);
                            }
                        }
                    }
                }
                // 检查是否是 lib.rs
                else if file_name.ends_with("lib.rs") {
                    log::info!("修复 lib.rs 中的 {} 个错误", file_errors.len());
                    
                    let lib_path = project_path.join("src").join("lib.rs");
                    if let Ok(current_content) = std::fs::read_to_string(&lib_path) {
                        log::info!("===== 修复前的 lib.rs 代码片段 =====");
                        log::info!("{}", &current_content[..current_content.len().min(500)]);
                        log::info!("===============================");
                        
                        match self.llm.fix_compile_errors(&current_content, &file_errors, &file_name).await {
                            Ok(fixed_content) => {
                                log::info!("===== 修复后的 lib.rs 代码片段 =====");
                                log::info!("{}", &fixed_content[..fixed_content.len().min(500)]);
                                log::info!("===============================");
                                
                                std::fs::write(&lib_path, &fixed_content)
                                    .with_context(|| format!("写入修复后的 lib.rs 失败: {:?}", lib_path))?;
                                fixed_any = true;
                            }
                            Err(e) => {
                                log::error!("修复 lib.rs 失败: {}", e);
                            }
                        }
                    }
                }
                else {
                    log::warn!("无法找到对应的模块文件: {}", file_name);
                }
            }
            
            if !fixed_any {
                log::warn!("本轮未能修复任何错误，停止自动修复");
                return Err(anyhow::anyhow!("自动修复失败：无法修复编译错误"));
            }
        }
        
        log::warn!("达到最大修复轮数({})，仍有编译错误", MAX_FIX_ITERATIONS);
        Err(anyhow::anyhow!("自动修复失败：达到最大重试次数"))
    }
}

